package com.tscnd.core.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import com.tscnd.core.dao.resource.IResourceDao;
import com.tscnd.core.dao.role.IRoleDao;
import com.tscnd.core.entity.resource.Resource;
import com.tscnd.core.entity.role.Role;


/**
 * 加载资源与权限的对应关系
 * 最核心的地方，就是提供某个资源对应的权限定义，即getAttributes方法返回的结果。 此类在初始化时，应该取到所有资源及其对应角色的定义。
 * 
 */
public class MySecurityMetadataSource  implements FilterInvocationSecurityMetadataSource {
	
	private static final Logger logger = Logger.getLogger(MySecurityMetadataSource.class);
	
	private static Map<String, Collection<ConfigAttribute>> resourceMap = null;  
	// private AntUrlPathMatcher urlMatcher;
	

	 private IRoleDao roleDao;

	 private IResourceDao resourceDao;
	 
	 private RequestMatcher pathMathcher;
	 
	 //初始化构造器
    public MySecurityMetadataSource(IRoleDao roleDao,IResourceDao resourceDao) {
    	this.roleDao=roleDao;
    	this.resourceDao=resourceDao;
    	loadResourceDefine();
    } 
	
  //加载所有资源与权限的关系  
    private void loadResourceDefine() {
    	logger.info("用户权限加载....");
		System.out.println("加载所有资源与权限的关系...");
    	/* 
    	 * 将权限 和资源的url地址存进Map中<key为url地址,value为权限>
    	 * 先查询出所有的权限，将权限封装到ConfigAttribute对象中
    	 * 然后根据权限查出对应所有的资源中的url路径，并将url为键，权限集合为值 存进Map中。
    	 * 
    	 */
    	try {
    		if(resourceMap==null){
    			resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
				List<Role> roles=roleDao.getAll();
				//从角色中给对应的资源授权
    			for (Role role : roles)
				{
    				ConfigAttribute ca = new SecurityConfig(role.getAuthorityMark());//将标记设置成可配置的属性
    				List<Resource>resources= resourceDao.findRoleByResource(role.getId());
    				for (Resource resource : resources)
					{
    					String url = resource.getResourcePath();
    					/*
					     * 判断资源文件和权限的对应关系，如果已经存在相关的资源url，则要通过该url为key提取出权限集合，将权限增加到权限集合中。
					     */
					    if (resourceMap.containsKey(url)) {
					    	Collection<ConfigAttribute> value = resourceMap.get(url);
					     	value.add(ca);
					     	resourceMap.put(url, value);
					    }else{
					    	Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
						     atts.add(ca);
						     resourceMap.put(url, atts);
					    }
					}
				}
    		}	
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

    }  
    
    
    
	
    // 根据URL，找到相关的权限配置。
	@Override
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException
	{
		String requestUrl = ((FilterInvocation) object).getRequestUrl();
		int rUrlIndex = requestUrl.indexOf("?");
		if (rUrlIndex != -1)
		{
			requestUrl = requestUrl.substring(0, rUrlIndex);
		}

		Iterator<String> ite = resourceMap.keySet().iterator();
		while (ite.hasNext())
		{
			String resURL = ite.next();
			pathMathcher = new AntPathRequestMatcher(resURL);
			// 验证浏览器url和资源中url的匹配问题如用/aaa.action?str=123 是匹配/aaa.action** 是可以的
			if (pathMathcher.matches(((FilterInvocation) object).getRequest()))
			{
				// 从map取出当前url对应的所有权限
				return resourceMap.get(resURL);
			}
		}
		// 如果没有取到则返回一个带"ROLE_NO_USER"的对象
		Collection<ConfigAttribute> returnaAttributes = new ArrayList<ConfigAttribute>();
		returnaAttributes.add(new SecurityConfig("ROLE_NO_USER"));
		return returnaAttributes;
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		// TODO Auto-generated method stub
		//要改为true
		return true;
	}

}
